﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace Common
{
	public interface ICommand
	{
		bool Answer { get; }
		int Column { get; }
		int Row { get; }
		string User { get; }
		string Message { get; }
		ClientCommandType ComTypeClient { get; }
		ServerCommandType ComTypeServer { get; }
	}

	[Serializable]
	public class ClientCommand : ICommand
	{
		public bool Answer { get; set; }
		public int Column { get;  set; }
		public int Row { get;  set; }
		public string User { get; set; }
		public string Message { get;  set; }
		public ClientCommandType ComTypeClient { get;  set; }
		public ServerCommandType ComTypeServer { get;  set; }

        public ClientCommand():this( ClientCommandType.Null, ServerCommandType.Null,"",-1,-1, "", false) { }
		public ClientCommand(string user) : this(ClientCommandType.Alive, ServerCommandType.Null, user, -1, -1, "", false) { } // Alive message
		public ClientCommand(ClientCommandType ct, string user, int col, int row, string msg) : this(ct, ServerCommandType.Null, user, col, row, msg, false) { } // (Make move / move result)  message
		public ClientCommand(ClientCommandType ct, string user, string msg) : this(ct, ServerCommandType.Null, user, -1, -1, msg, false) { } // Generic message
		public ClientCommand(ClientCommandType ct, string user, bool answer) : this(ct, ServerCommandType.Null, user, -1, -1, "", answer) { } // Generic true/false
		public ClientCommand(ClientCommandType ct, string user, string msg, bool answer) : this(ct, ServerCommandType.Null, user, -1, -1, msg, answer) { } // Game Accept
		public ClientCommand(string user, string pwd) : this(ClientCommandType.Login, ServerCommandType.Null, user, -1, -1, pwd, false) { } // Login message
		public ClientCommand(ServerCommand serverCmd, string user, bool answer) : this(ClientCommandType.Answer, serverCmd.ComTypeServer, user, -1, -1, "", answer) { } // Response to server command
		private ClientCommand(ClientCommandType clientCT, ServerCommandType serverCT,string user, int col, int row, string msg, bool answer)
		{
			if (clientCT == ClientCommandType.GameMove && (col == -1 || row == -1))
				throw new Exception("Error!");
			if (clientCT == ClientCommandType.Login && user == "")
				throw new Exception("Error!");
			ComTypeClient = clientCT;
			ComTypeServer = serverCT;
			User = user;
			Column = col;
			Row = row;
			Message = msg;
			Answer = answer;
		} // Private constractor
	}

	[Serializable]
	public class ServerCommand : ICommand
	{
        public bool Answer { get;  set; }
		public int Column { get;  set; }
		public int Row { get;  set; }
		public string User { get;  set; }
		public string Message { get;  set; }
		public ServerCommandType ComTypeServer { get;  set; }
		public ClientCommandType ComTypeClient { get;  set; }


        public ServerCommand() : this(ClientCommandType.Null, ServerCommandType.Null, "", -1, -1, "", false) { }
		public ServerCommand(string user) : this(ClientCommandType.Null, ServerCommandType.IsAlive, user, -1, -1, "", false) { } // Check if user is alive
		public ServerCommand(ClientCommandType clientCT, string user, bool answer) : this(clientCT, ServerCommandType.Answer, user, -1, -1, "", answer) { } // Answer to request
		public ServerCommand(ServerCommandType serverCT, string user, string msg) : this(ClientCommandType.Null, serverCT, user, -1, -1, msg, false) { } // Send message to client
		public ServerCommand(ServerCommandType serverCT, string user, int col, int row, string msg) : this(ClientCommandType.Null, serverCT, user, col, row, msg, false) { } // (Make move / move result)  message
		private ServerCommand(ClientCommandType clientCT, ServerCommandType serverCT, string user, int col, int row, string msg, bool answer)
		{
			ComTypeClient = clientCT;
			ComTypeServer = serverCT;
			User = user;
			Column = col;
			Row = row;
			Message = msg;
			Answer = answer;
		} // Private constractor
	}

	[Serializable]
	public enum ClientCommandType
	{
        Null, // Nothing
		Login, // Login (username, password)
		Logout, // Logout ()
		GameOpen, // Open new game ()
		GameRequest, // Request for playing ()
		GameAccept, // Accept to opponent's request ()
		GameReady, // Ready after battles design ()
		GameMove, // Make move (column, row)
		GameMoveResuslt, // move result (Hit Type)
		GameNew, // Accept new game ()
		GameResign, // Resign ()
		Alive, // I'm alive ()
		Message, // Send message to opponent (msg)
		OpenGames, // Get open games list from server
		Answer // Answer to server's request
	}

	[Serializable]
	public enum ServerCommandType
	{
        Null, // Nothing
		Answer, // General response to client's request (true/false)
		GameAccepted, // Opponent accepted the user's request
		GameRequested, // Opponent request client's game
		GameNew, // New game requested
		OpponentReady, // Opponent is ready
		MoveResult, // Move result (HitType)
		RedirectMove, // Redirect move to opponent (column, row)
		Resign,
		IsAlive, // Is the client is still connected ()
		OnlineList, // List of online users (list)
		OpenGames, // List of open games (list)
		Message // Send message to opponent (username, msg)
	}
}